<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../style/journal.css" type="text/css" />
<style type="text/css"><!--
.googleadsense {
	margin: 2px;
	padding: 0px;
//--></style><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-65008-1";
urchinTracker();
</script><title>Scalar::Util, List::Util, List::MoreUtils</title>
</head>
<body>
<a href="index.html">Journal</a>(2005) | <a href="../blog/"><b>Blog</b></a>(2006) | <a href="http://www.fayland.org/cgi-bin/random_link.pl">RandomLink</a> | <a href="AboutFayland.html">WhoAmI</a> | <a href="LiveBookmark.html">LiveBookmark</a> | <a href="http://www.fayland.org/">HomePage</a>
<p><&lt;Previous: <a href="PBP2.html">Tips from Perl Best Practices</a>&nbsp;&nbsp;>>Next: <a href="PBP3.html">Tips from Perl Best Practices, Part 2</a></p>
<h1>Scalar::Util, List::Util, List::MoreUtils</h1>
<div class='content'>
<p>Category: <a href='Modules.html'>Modules</a> &nbsp; Keywords: <b>scalar list</b></p><p>Util 是 Utility 的缩写，意为有用的工具。<br />
此三模块以前看过但没用过，昨晚在 Perl Best Practices 里听 Damain Conway 又提及。觉得用处挺大的，就简单翻译下用途。需要的参阅 perldoc, 此三模块在 5.8 后为标准模块，安装 Perl 后就有了。</p>

<h3>Scalar::Util</h3>

<h4>blessed $scalar</h4>
如果 $scalar 是一个对象的引用，则返回这个对象的类的名字，否则返回 undef

<h4>refaddr $scalar</h4>
如果 $scalar 是一个引用，则返回一个数字代表该引用的所指向的内存地址，否则返回 undef<br />
这个可以对两个变量是否同一提供判断。

<h4>reftype $scalar</h4>
如果 $scalar 是一个引用，则返回相应的类型值（如 'SCALAR', 'HASH', 'ARRAY', 'CODE', 'Regexp'），否则返回 undef

<h4>readonly $scalar</h4>
如果 $scalar 只读返回真

<h4>openhandle $scalar</h4>
如果不是一个文件句柄或着该文件句柄没有开着的话，返回 undef


<pre>use Scalar::Util qw/openhandle/;

open(FH, 'nonexist');
print openhandle(*FH); # 返回 undef

open(FILE, 'exist');
print openhandle(*FILE); # 返回如 GLOB(0x162538c)
close(FILE);
print openhandle(*FILE); # 返回 undef
</pre>



<h4>weaken $scalar/is_weak $scalar</h4>
使用这个对防止循环数据结构的内存泄露有帮助。详细参阅该书和 perldoc

<h4>dualvar <span class="caps">NUM, STRING</span></h4>
设置一个变量在数字环境和字符串环境下返回不同的值。


<pre>$foo = dualvar 10, &quot;Hello&quot;;
$num = $foo + 2;                    # 12
$str = $foo . &quot; world&quot;;             # Hello world</pre>



<h4>looks_like_number, set_prototype etc.</h4>
参阅书籍或 perldoc Scalar::Util

<h3>List::Util</h3>

<h4>first { <code>&lt;condition&gt;</code> } @list</h4>
返回 @list 中满足该 condition 的第一个元素。该函数与 grep 有点类似，但它是搜寻到第一个匹配时就停止了，而 grep 要搜索完整个 @list

<h4>max/min @list</h4>
返回数组中用 &gt;/&lt; 号比较后的最大最小值

<h4>maxstr/minstr @list</h4>
返回数组中用 gt/lt 比较后的最大最小值

<h4>shuffle @list</h4>
象 ipod shuffle 一样，随机在 @list 挑一个元素

<h4>sum @list</h4>
对整个 @list 求和，然后返回值

<h4>reduce <span class="caps">BLOCK LIST</span></h4>
这个其实挺有用的。上面的这些 max, min, first, sum 等都可以用 reduce 来操作。<br />
该函数首先将 <span class="caps">LIST </span>中的第一和第二个元素赋予 $a 和 $b （与 sort 有点类似），然后执行 <span class="caps">BLOCK, </span>将其返回值赋予 $a, 然后取第三个元素赋予 $b, 再执行 <span class="caps">BLOCK, </span>就这样多次执行，然后返回值。


<pre>$foo = reduce { $a &lt; $b ? $a : $b } 1..10; # 这句与 min 1..10 一样效果
$foo = reduce { defined($a) ? $a : defined($b) ? $b : undef } undef, @list; # 这句效果与 $foo = first { defined($_) } @list 同
my $overall_probablity = reduce { $a * $b } @partial_probabilities; # 将列表中的所有元素相乘</pre>



<h3>List::MoreUtils</h3>

<h4>all/any/notall/none { <code>&lt;condition&gt;</code> } @list</h4>


<pre># @list 中有任意一个元素有定义
print &quot;At least one value undefined&quot; if any { !defined($_) } @list;

# @list 中所有的元素都有定义
print &quot;All items defined&quot; if all { defined($_) } @list;

# @list 中没有元素被定义，它是 any 的反义
print &quot;No value defined&quot; if none { defined($_) } @list;

# @list 中至少有一个元素没定义，它是 all 的反义
print &quot;Not all values defined&quot; if notall { defined($_) } @list;</pre>



<h4>first_index { <code>&lt;condition&gt;</code> } @list</h4>
返回第一个满足条件的列表索引号。last_index 返回最后一个满足的索引号。没有找到满足的都返回 -1


<pre>my @list = (1, 4, 3, 2, 4, 6);
printf &quot;item with index %i in list is 4&quot;, firstidx { $_ == 4 } @list;
__END__
item with index 1 in list is 4</pre>



<h4>apply { <code>&lt;transform&gt;</code> } @list</h4>
对于每个 @list 中的元素执行 transform, 然后在列表环境下返回改变后的列表，在标量环境下返回最后一个值。<br />
它与 map 有点类似，但是 apply 不改变原来 @list 的值。


<pre>my @list = (1 .. 4);
my @mult = apply { $_ *= 2 } @list;
print &quot;\@list = @list\n&quot;;
print &quot;\@mult = @mult\n&quot;;
__END__
@list = 1 2 3 4
@mult = 2 4 6 8</pre>




<pre>my @nice_words = apply { s/$EXPLETIVE/[DELETED]/gxms } @words;

# 这面的这句如果用 map 写的话
my @nice_words
    = map {
          my $copy = $_;
          $copy =~ s/$EXPLETIVE/[DELETED]/gxms;
          $copy;
      } @words;</pre>



<h4>after/before <span class="caps">BLOCK LIST</span></h4>
返回满足 <span class="caps">BLOCK </span>后面或前面的列表元素。如


<pre>@x = after { $_ % 5 == 0 } (1..9);    # returns 6, 7, 8, 9</pre>


<p>而 after_incl/before_incl 也包括满足 <span class="caps">BLOCK </span>的元素，如上面就会多一个 5</p>

<h4>pairwise <span class="caps">BLOCK ARRAY1 ARRAY2</span></h4>
将 <span class="caps">ARRAY1 </span>与 <span class="caps">ARRAY2 </span>对应平行的元素（设置成 $a 和 $b）做 <span class="caps">BLOCK </span>后返回。如


<pre>@a = (1 .. 5);
@b = (11 .. 15);
@x = pairwise { $a + $b } @a, @b;	# returns 12, 14, 16, 18, 20

# mesh with pairwise
@a = qw/a b c/;
@b = qw/1 2 3/;
@x = pairwise { ($a, $b) } @a, @b;	# returns a, 1, b, 2, c, 3</pre>


<p>如果数组元素个数不同的话，自己试验下。<br />
注意这里的 $a 和 $b 是绑定数组元素，所以如果对 $a/$b 进行更改的话会对应修改数组。</p>

<h4>zip/mesh @array1, @array2, ...</h4>
跟 Perl 6 中一样。不同数组依次取一个，然后循环。


<pre>@x = qw/a b c d/;
@y = qw/1 2 3 4/;
@z = zip @x, @y;	    # returns a, 1, b, 2, c, 3, d, 4</pre>



<h4>uniq @list</h4>
uniq 是 unique 的缩写，独一无二的。


<pre>my @x = uniq 1, 1, 2, 2, 3, 5, 3, 4; # returns 1 2 3 5 4
my $x = uniq 1, 1, 2, 2, 3, 5, 3, 4; # returns 5 不同的个数
</pre>



<h4>Others</h4>

<ul>
<li>insert_after <span class="caps">BLOCK VALUE LIST </span>/ 在满足 <span class="caps">BLOCK </span>的列表元素后插入 <span class="caps">VALUE</span></li>
<li>insert_after_string <span class="caps">STRING VALUE LIST </span>/ 在等于 <span class="caps">STRING </span>的列表元素后插入 <span class="caps">VALUE</span></li>
<li>indexes <span class="caps">BLOCK LIST </span>/ 与 first_index 不同，它返回一个由所有的索引号组成的列表</li>
</ul>

<p>不想写太多了。详细的查阅文档。其实不是 Perl 不够强大，只是你没发现而已。</p></div>
<p><&lt;Previous: <a href="PBP2.html">Tips from Perl Best Practices</a>&nbsp;&nbsp;>>Next: <a href="PBP3.html">Tips from Perl Best Practices, Part 2</a></p>
<p><strong>Options:</strong> <a href='http://del.icio.us/post?title=Scalar::Util,%20List::Util,%20List::MoreUtils&url=http://www.fayland.org/journal/Utils.html'>+Del.icio.us</a></p>
<strong>Related items</strong>
<ul><li><a href='PBP2.html'>Tips from Perl Best Practices</a> < <span class='digit'>2005-09-13 16:57:52</span> ></li><li><a href='PBP3.html'>Tips from Perl Best Practices, Part 2</a> < <span class='digit'>2005-09-22 00:29:34</span> ></li></ul>
Created on <span class="digit">2005-09-14 08:52:14</span>, Last modified on <span class="digit">2005-09-14 09:37:57</span><br />
Copyright 2004-2005 All Rights Reserved. Powered by <a href="Eplanet.html">Eplanet</a> && <a href='http://catalyst.perl.org'>Catalyst</a> 5.62.
</body>
</html>